home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
17 Bit Software 3: The Continuation
/
17-Bit_The_Continuation_Disc.iso
/
amigan
/
amigan 8
/
mklev.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-27
|
15KB
|
668 lines
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* mklev.c version 1.0.1 - new makecorridor() */
#ifndef MKLEV
#define MKLEV
#endif
#include <stdio.h>
#include "hack.h"
#include "def.trap.h"
extern struct monst *makemon();
static char tspe[2],**args;
static int doorindex;
static schar nxcor;
char ismklev;
struct mkroom *croom, *troom;
boolean goldseen;
int nroom;
int smeq[MAXNROFROOMS+1];
char *tfile;
#ifdef WIZARD
extern boolean wizard;
#endif
#define somex() ((rand()%(croom->hx-croom->lx+1))+croom->lx)
#define somey() ((rand()%(croom->hy-croom->ly+1))+croom->ly)
extern char nul[40];
extern struct rm levl[COLNO][ROWNO];
extern struct monst *fmon;
extern struct obj *fobj;
extern struct gen *fgold, *ftrap;
extern char *fut_geno; /* monsters that should not be created anymore */
extern struct mkroom rooms[MAXNROFROOMS+1];
extern coord doors[DOORMAX];
extern int comp();
extern xchar dlevel;
extern xchar xdnstair,xupstair,ydnstair,yupstair;
zeroout(addr, len)
char *addr;
int len;
{
while(--len>0) *addr++=0;
}
mklev()
{
register unsigned tryct;
tfile = lock;
troom = NULL;
doorindex = 0;
nroom = 0;
if(getbones()) return;
ismklev = 1;
if(dlevel < rn1(3, 26)) tspe[0] = 'a'; /* normal level */
else tspe[0] = 'b'; /* maze */
tspe[1] = 0;
/* zap the object bases */
{int i;extern int bases[];
for(i=0;i<15;bases[i++]=0);}
/* zap the room pictures */
zeroout(levl,COLNO*ROWNO*sizeof(struct rm));
fmon = NULL;
fobj = NULL;
fgold = ftrap = NULL;
zeroout( doors, sizeof(coord)*DOORMAX);
xdnstair = xupstair = ydnstair = yupstair = 0;
zeroout(rooms, (MAXNROFROOMS+1)*sizeof(struct mkroom));
init_objects();
rooms[0].hx = -1; /* in case we are in a maze */
/* a: normal; b: maze */
if(*tspe == 'b') {
makemaz();
#ifdef DOSAVE
{
int fd;
if((fd = creat(tfile,FMASK)) < 0)
panic("Cannot create %s\n", tfile);
savelev(fd);
close(fd);
}
#endif
ismklev = 0;
return(0);
}
/* construct the rooms */
while(nroom < (MAXNROFROOMS/3)) {
croom = rooms;
nroom = 0;
(void) makerooms(0); /* not secret */
}
/* for each room: put things inside */
for(croom = rooms; croom->hx > 0; croom++) {
/* put a sleeping monster inside */
if(!rn2(3)) (void)
makemon((struct permonst *) 0, somex(), somey());
/* put traps and mimics inside */
goldseen = FALSE;
while(!rn2(8-(dlevel/6))) mktrap(0,0);
if(!goldseen && !rn2(3)) mkgold(0,somex(),somey());
if(!rn2(3)) {
mkobj_at(0, somex(), somey());
tryct = 0;
while(!rn2(5)) {
if(++tryct > 100){
myprintf("tryct overflow4\n");
break;
}
mkobj_at(0, somex(), somey());
}
}
}
tryct = 0;
do {
if(++tryct > 1000) panic("Cannot make dnstairs\n");
croom = &rooms[rn2(nroom)];
xdnstair = somex();
ydnstair = somey();
} while((*tspe =='n' && (!(xdnstair%2) || !(ydnstair%2))) ||
g_at(xdnstair,ydnstair,ftrap));
levl[xdnstair][ydnstair].scrsym ='>';
levl[xdnstair][ydnstair].typ = STAIRS;
troom = croom;
do {
if(++tryct > 2000) panic("Cannot make upstairs\n");
croom = &rooms[rn2(nroom)];
xupstair = somex();
yupstair = somey();
} while(croom == troom || m_at(xupstair,yupstair) ||
g_at(xupstair,yupstair,ftrap));
levl[xupstair][yupstair].scrsym ='<';
levl[xupstair][yupstair].typ = STAIRS;
#ifdef DEBUG
dumpit();
#endif
qsort((char *) rooms, nroom, sizeof(struct mkroom), comp);
makecorridors();
make_niches();
/* make a secret treasure vault, not connected to the rest */
if(nroom < (2*MAXNROFROOMS/3)) if(!rn2(3)) {
register int x,y;
troom = croom = &rooms[nroom];
if(makerooms(1)) { /* make secret room */
troom->rtype = 6; /* treasure vault */
for(x = troom->lx; x <= troom->hx; x++)
for(y = troom->ly; y <= troom->hy; y++)
mkgold(rnd(dlevel*100) + 50, x, y);
if(!rn2(3))
makevtele();
}
}
#ifdef WIZARD
if(wizard){
if(rn2(3)) mkshop(); else mkzoo();
} else
#endif WIZARD
if(dlevel > 1 && dlevel < 20 && rn2(dlevel) < 2)
mkshop();
else
if(dlevel > 6 && !rn2(7) )
mkzoo();
#ifdef DOSAVE
{
int fd;
if((fd = creat(tfile,FMASK)) < 0)
panic("Cannot create %s\n", tfile);
savelev(fd);
close(fd);
}
#endif
ismklev = 0;
return(0);
}
makerooms(secret)
int secret;
{
register int lowx, lowy;
register int tryct = 0;
while(nroom < (MAXNROFROOMS/2) || secret)
for(lowy = rn1(3,3); lowy < ROWNO-7; lowy += rn1(2,4))
{
for(lowx = rn1(3,4); lowx < COLNO-10; lowx += rn1(2,7))
{
if (tryct++ > 10000) return(0);
if ((lowy += (rn2(5)-2)) < 3)
lowy = 3;
else
if(lowy > ROWNO-6)
lowy = ROWNO-6;
if(levl[lowx][lowy].typ) continue;
if ((secret && maker(lowx, 1, lowy, 1)) ||
(!secret && maker(lowx,rn1(9,2),lowy,rn1(4,2))
&& nroom+2 > MAXNROFROOMS)) return(1);
}
}
return(1);
}
comp(x,y)
register struct mkroom *x,*y;
{
if(x->lx < y->lx) return(-1);
return(x->lx > y->lx);
}
coord
finddpos(xl,yl,xh,yh) {
coord ff;
register int x,y;
ff.x = (xl == xh) ? xl : (xl + rn2(xh-xl+1));
ff.y = (yl == yh) ? yl : (yl + rn2(yh-yl+1));
if(okdoor(ff.x, ff.y)) return(ff);
if(xl < xh) for(x = xl; x <= xh; x++)
if(okdoor(x, ff.y)){
ff.x = x;
return(ff);
}
if(yl < yh) for(y = yl; y <= yh; y++)
if(okdoor(ff.x, y)){
ff.y = y;
return(ff);
}
return(ff);
}
/* if allowable, create a door at [x,y] */
okdoor(x,y)
register int x,y;
{
if(levl[x-1][y].typ == DOOR || levl[x+1][y].typ == DOOR ||
levl[x][y+1].typ == DOOR || levl[x][y-1].typ == DOOR ||
levl[x-1][y].typ == SDOOR || levl[x+1][y].typ == SDOOR ||
levl[x][y-1].typ == SDOOR || levl[x][y+1].typ == SDOOR ||
(levl[x][y].typ != HWALL && levl[x][y].typ != VWALL) ||
doorindex >= DOORMAX)
return(0);
return(1);
}
dodoor(x,y,aroom)
register int x,y;
register struct mkroom *aroom;
{
if(doorindex >= DOORMAX) panic("DOORMAX exceeded?");
if(!okdoor(x,y) && nxcor) return;
dosdoor(x,y,aroom,rn2(8) ? DOOR : SDOOR);
}
dosdoor(x,y,aroom,type)
register int x,y;
register struct mkroom *aroom;
register int type;
{
register struct mkroom *broom;
register int tmp;
levl[x][y].typ = type;
if(type == DOOR)
levl[x][y].scrsym ='+';
aroom->doorct++;
broom = aroom+1;
if(broom->hx < 0) tmp = doorindex; else
for(tmp = doorindex; tmp > broom->fdoor; tmp--)
doors[tmp] = doors[tmp-1];
doorindex++;
doors[tmp].x = x;
doors[tmp].y = y;
for( ; broom->hx >= 0; broom++) broom->fdoor++;
}
/* Only called from makerooms() */
maker(lowx,ddx,lowy,ddy)
schar lowx,ddx,lowy,ddy;
{
register int x, y, hix = lowx+ddx, hiy = lowy+ddy;
if(nroom >= MAXNROFROOMS) return(0);
if(hix > COLNO-5) hix = COLNO-5;
if(hiy > ROWNO-4) hiy = ROWNO-4;
chk:
if(hix <= lowx || hiy <= lowy) return(0);
/* check area around room (and make room smaller if necessary) */
for(x = lowx-4; x <= hix+4; x++)
for(y = lowy-3; y <= hiy+3; y++)
if(levl[x][y].typ) {
if(rn2(3)) return(0);
lowx = x+5;
lowy = y+4;
goto chk;
}
/* on low levels the room is lit (usually) */
/* secret vaults are always lit */
if((rnd(dlevel) < 10 && rn2(77)) || (ddx == 1 && ddy == 1))
for(x = lowx-1; x <= hix+1; x++)
for(y = lowy-1; y <= hiy+1; y++)
levl[x][y].lit = 1;
croom->lx = lowx;
croom->hx = hix;
croom->ly = lowy;
croom->hy = hiy;
croom->rtype = croom->doorct = croom->fdoor = 0;
for(x = lowx-1; x <= hix+1; x++)
for(y = lowy-1; y <= hiy+1; y += (hiy-lowy+2)) {
levl[x][y].scrsym = '-';
levl[x][y].typ = HWALL;
}
for(x = lowx-1; x <= hix+1; x += (hix-lowx+2))
for(y = lowy; y <= hiy; y++) {
levl[x][y].scrsym = '|';
levl[x][y].typ = VWALL;
}
for(x = lowx; x <= hix; x++)
for(y = lowy; y <= hiy; y++) {
levl[x][y].scrsym = '.';
levl[x][y].typ = ROOM;
}
croom++;
croom->hx = -1;
smeq[nroom] = nroom;
nroom++;
return(1);
}
makecorridors() {
register int a,b;
nxcor = 0;
for(a = 0; a < nroom-1; a++)
join(a, a+1);
for(a = 0; a < nroom-2; a++)
if(smeq[a] != smeq[a+2])
join(a, a+2);
for(a = 0; a < nroom; a++)
for(b = 0; b < nroom; b++)
if(smeq[a] != smeq[b])
join(a, b);
if(nroom > 2)
for(nxcor = rn2(nroom) + 4; nxcor; nxcor--) {
a = rn2(nroom);
b = rn2(nroom-2);
if(b >= a) b += 2;
join(a, b);
}
}
join(a,b)
register int a,b;
{
coord cc,tt;
register int tx, ty, xx, yy;
register struct rm *crm;
register int dx, dy, dix, diy, cct;
croom = &rooms[a];
troom = &rooms[b];
/* find positions cc and tt for doors in croom and troom
and direction for a corridor between them */
if(troom->hx < 0 || croom->hx < 0 || doorindex >= DOORMAX) return;
if(troom->lx > croom->hx) {
dx = 1;
dy = 0;
xx = croom->hx+1;
tx = troom->lx-1;
cc = finddpos(xx,croom->ly,xx,croom->hy);
tt = finddpos(tx,troom->ly,tx,troom->hy);
} else if(troom->hy < croom->ly) {
dy = -1;
dx = 0;
yy = croom->ly-1;
cc = finddpos(croom->lx,yy,croom->hx,yy);
ty = troom->hy+1;
tt = finddpos(troom->lx,ty,troom->hx,ty);
} else if(troom->hx < croom->lx) {
dx = -1;
dy = 0;
xx = croom->lx-1;
tx = troom->hx+1;
cc = finddpos(xx,croom->ly,xx,croom->hy);
tt = finddpos(tx,troom->ly,tx,troom->hy);
} else {
dy = 1;
dx = 0;
yy = croom->hy+1;
ty = troom->ly-1;
cc = finddpos(croom->lx,yy,croom->hx,yy);
tt = finddpos(troom->lx,ty,troom->hx,ty);
}
xx = cc.x;
yy = cc.y;
tx = tt.x - dx;
ty = tt.y - dy;
if(nxcor && levl[xx+dx][yy+dy].typ)
return;
dodoor(xx,yy,croom);
cct = 0;
while(xx != tx || yy != ty) {
xx += dx;
yy += dy;
/* loop: dig corridor at [xx,yy] and find new [xx,yy] */
if(cct++ > 500 || (nxcor && !rn2(35)))
return;
if(xx == COLNO-1 || xx == 0 || yy == 0 || yy == ROWNO-1)
return; /* impossible */
crm = &levl[xx][yy];
if(!(crm->typ)) {
if(rn2(100)) {
crm->typ = CORR;
crm->scrsym = CORR_SYM;
} else {
crm->typ = SCORR;
crm->scrsym = ' ';
}
if(nxcor && !rn2(50)) {
mkobj_at(ROCK_SYM, xx, yy);
}
} else
if(crm->typ != CORR && crm->typ != SCORR) {
/* strange ... */
return;
}
/* find next corridor position */
dix = abs(xx-tx);
diy = abs(yy-ty);
/* do we have to change direction ? */
if(dy && dix > diy) {
register int ddx = (xx > tx) ? -1 : 1;
crm = &levl[xx+ddx][yy];
if(!crm->typ || crm->typ == CORR || crm->typ == SCORR) {
dx = ddx;
dy = 0;
continue;
}
} else if(dx && diy > dix) {
register int ddy = (yy > ty) ? -1 : 1;
crm = &levl[xx][yy+ddy];
if(!crm->typ || crm->typ == CORR || crm->typ == SCORR) {
dy = ddy;
dx = 0;
continue;
}
}
/* continue straight on? */
crm = &levl[xx+dx][yy+dy];
if(!crm->typ || crm->typ == CORR || crm->typ == SCORR)
continue;
/* no, what must we do now?? */
if(dx) {
dx = 0;
dy = (ty < yy) ? -1 : 1;
crm = &levl[xx+dx][yy+dy];
if(!crm->typ || crm->typ == CORR || crm->typ == SCORR)
continue;
dy = -dy;
continue;
} else {
dy = 0;
dx = (tx < xx) ? -1 : 1;
crm = &levl[xx+dx][yy+dy];
if(!crm->typ || crm->typ == CORR || crm->typ == SCORR)
continue;
dx = -dx;
continue;
}
}
/* we succeeded in digging the corridor */
dodoor(tt.x, tt.y, troom);
if(smeq[a] < smeq[b])
smeq[b] = smeq[a];
else
smeq[a] = smeq[b];
}
make_niches()
{
register int ct = rn2(nroom/2 + 1)+1;
while(ct--) makeniche(FALSE);
}
makevtele()
{
makeniche(TRUE);
}
makeniche(with_trap)
boolean with_trap;
{
register struct mkroom *aroom;
register struct rm *rm;
register int vct = 8;
coord dd;
register int dy,xx,yy;
register struct gen *gtmp;
if(doorindex < DOORMAX)
while(vct--) {
aroom = &rooms[rn2(nroom-1)];
if(aroom->rtype != 0) continue; /* not an ordinary room */
if(rn2(2)) {
dy = 1;
dd = finddpos(aroom->lx,aroom->hy+1,aroom->hx,aroom->hy+1);
} else {
dy = -1;
dd = finddpos(aroom->lx,aroom->ly-1,aroom->hx,aroom->ly-1);
}
xx = dd.x;
yy = dd.y;
if((rm = &levl[xx][yy+dy])->typ) continue;
if(with_trap || !rn2(4)) {
rm->typ = SCORR;
rm->scrsym = ' ';
if(with_trap) {
gtmp = newgen();
gtmp->gx = xx;
gtmp->gy = yy+dy;
gtmp->gflag = TELEP_TRAP | ONCE;
gtmp->ngen = ftrap;
ftrap = gtmp;
make_engr_at(xx,yy-dy,"ad ae?ar um");
}
dosdoor(xx,yy,aroom,SDOOR);
} else {
rm->typ = CORR;
rm->scrsym = CORR_SYM;
if(rn2(7))
dosdoor(xx,yy,aroom,rn2(5) ? SDOOR : DOOR);
else {
mksobj_at(SCROLL_SYM,SCR_TELEPORTATION,xx,yy+dy);
if(!rn2(3)) mkobj_at(0,xx,yy+dy);
}
}
return;
}
}
/* make a trap somewhere (in croom if mazeflag = 0) */
mktrap(num,mazeflag)
register int num,mazeflag;
{
register struct gen *gtmp;
register int kind,nopierc,nomimic,fakedoor,fakegold,tryct = 0;
register xchar mx,my;
if(!num || num >= TRAPNUM) {
nopierc = (dlevel < 4) ? 1 : 0;
nomimic = (dlevel < 9 || goldseen ) ? 1 : 0;
if(index(fut_geno, 'M')) nomimic = 1;
kind = rn2(TRAPNUM - nopierc - nomimic);
/* note: PIERC = 7, MIMIC = 8, TRAPNUM = 9 */
} else kind = num;
if(kind == MIMIC) {
register struct monst *mtmp;
fakedoor = (!rn2(3) && !mazeflag);
fakegold = (!fakedoor && !rn2(2));
if(fakegold) goldseen = TRUE;
do {
if(++tryct > 200) return;
if(fakedoor) {
/* note: fakedoor maybe on actual door */
if(rn2(2)){
if(rn2(2))
mx = croom->hx+1;
else mx = croom->lx-1;
my = somey();
} else {
if(rn2(2))
my = croom->hy+1;
else my = croom->ly-1;
mx = somex();
}
} else if(mazeflag) {
extern coord mazexy();
coord mm;
mm = mazexy();
mx = mm.x;
my = mm.y;
} else {
mx = somex();
my = somey();
}
} while(m_at(mx,my));
if(mtmp = makemon(PM_MIMIC,mx,my))
mtmp->mimic =
fakegold ? '$' : fakedoor ? '+' :
(mazeflag && rn2(2)) ? AMULET_SYM :
"=/)%?![<>" [ rn2(9) ];
return;
}
gtmp = newgen();
gtmp->gflag = kind;
do {
if(++tryct > 200){
free((char *) gtmp);
return;
}
if(mazeflag){
extern coord mazexy();
coord mm;
mm = mazexy();
gtmp->gx = mm.x;
gtmp->gy = mm.y;
} else {
gtmp->gx = somex();
gtmp->gy = somey();
}
} while(g_at(gtmp->gx, gtmp->gy, ftrap));
gtmp->ngen = ftrap;
ftrap = gtmp;
if(mazeflag && !rn2(10) && gtmp->gflag < PIERC) gtmp->gflag |= SEEN;
}
#ifdef DEBUG
dumpit()
{
int x, y;
struct rm *room;
cgetret();
/* kludge in making everything visible */
for(y=0; y < ROWNO; y++)
for(x=0; x < COLNO-3; x++)
if ( (room = &levl[x][y])->typ)
at(x,y, (room->scrsym) ? room->scrsym : '¿');
}
#endif